#include "Thread.h"

#include "SocketException.h"
#include "WinException.h"


void Thread::sleep(int milliseconds) {
		
	DWORD result = ::WaitForSingleObject(mEvent, milliseconds);

	switch(result) {
	case WAIT_OBJECT_0: break; //event was signaled
	case WAIT_FAILED: throw WinException("Thread::sleep(): WaitForSingleObject()", GetLastError());
	case WAIT_TIMEOUT: break; // the timeout has elapsed
	};
}


void Thread::stop() {}

void Thread::wakeUp() {
	// signal the sleep()-event thus awakening the thread
	if (!::SetEvent(mEvent)) throw WinException("Thread::wakeUp(): SetEvent()",GetLastError());
}


void Thread::join() {
	// wait until the thread has returned from the run() method
	DWORD result = ::WaitForSingleObject(mHandle, INFINITE);
	switch(result) {
	case WAIT_OBJECT_0: break;
	case WAIT_TIMEOUT: break;
	case WAIT_FAILED: throw WinException("Thread::join(): WaitForSingleObject", GetLastError());
	};
}


Thread::Thread() 
	: mHandle(INVALID_HANDLE_VALUE)
{
	// create an automatically resetting event
	// to allow this thread to sleep in an interruptable way (see Thread::sleep())
	mEvent = ::CreateEvent( NULL, 0, 0, NULL);
	if (mEvent == NULL) throw WinException("Thread::Thread(): CreateEvent()",GetLastError());
}


void Thread::start() {
	if (mHandle == INVALID_HANDLE_VALUE) {
		// start the thread only if it is not already running
		mHandle = ::CreateThread(NULL,0, threadFunc, this, 0, NULL);
		if (mHandle == NULL) throw WinException("Thread::start(): CreateThread()", GetLastError());
	}
}
	
Thread::~Thread() {
	// Close all used handles
	if (mHandle != INVALID_HANDLE_VALUE) ::CloseHandle(mHandle);
	if (mEvent  != NULL) ::CloseHandle(mEvent);
}



DWORD WINAPI Thread::threadFunc( void* thisptr) {
	Thread* pThread = (Thread*)thisptr;
	pThread->run();
	// cleanup after execution
	::CloseHandle( pThread->mHandle);
	pThread->mHandle = INVALID_HANDLE_VALUE;
	return 0;
}
